/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * htap_infra.h
 * Interface for HTAP entry point Facade.
 *
 * IDENTIFICATION
 * src/include/storage/htap/htap_infra.h
 *
 * -------------------------------------------------------------------------
 */

#ifndef HTAP_INFRA_H
#define HTAP_INFRA_H

#include <unordered_map>
#include "knl/knl_thread.h"
#include "knl/knl_session.h"
#include "executor/exec/execdesc.h"
#include "nodes/parsenodes_common.h"
#include "access/tupdesc.h"
#include "utils/relcache.h"
#include "utils/elog.h"
#include "access/xact.h"
#include "nodes/parsenodes.h"
#include "utils/memutils.h"
#include "htap_cfg.h"

namespace htap {
class HTAPFlush;
class HTAPXLogRedoer;

class HTAPInfra {
public:

    static bool CreateInstance(const char *configFilePath);
    static void DestroyInstance();
    static HTAPInfra *GetInstance();

    static bool HTAPTxnEnsure(bool registerCallbacks = true);

    // get HTAP configuration
    inline HTAPCfg &GetCfg()
    {
        return m_cfg;
    }

    // get HTAP memory ctx
    MemoryContext CreateMemoryContext(MemoryContext parent, const char *name);

    // destroy HTAP memory ctx
    void DestroyMemoryContext(MemoryContext memoryContext);


    // get HTAP thread memory ctx
    MemoryContext GetThreadMemoryContext();

    // destroy HTAP thread memory ctx
    void DestroyThreadMemoryContext();

    // destroy HTAP session memory ctx
    void DestroySessionMemoryContext();

    // get HTAP Flush
    inline HTAPFlush *GetFlush()
    {
        return m_flush;
    }

    // get HTAP xlog redoer
    inline HTAPXLogRedoer *GetXLogRedoer()
    {
        return m_xLogRedoer;
    }

    ThreadId StartFlush();

    ThreadId StartXLogRedoer();

    /*
     * HTAP record exec-insert into delta table
     */
    RC OnInsertRow(Oid relationId, ItemPointer ctid, TupleTableSlot *slot);

    /*
     * HTAP record exec-delete into delta table
     */
    RC OnDeleteRow(Oid relationId, ItemPointer ctid);

    /*
     * HTAP record exec-update into delta table
     */
    RC OnUpdateRow(Oid relationId, ItemPointer oldCtid, ItemPointer newCtid, TupleTableSlot *slot);

    /*
     * HTAP exec create table
     */
    RC OnCreateTable(Oid parentId, Oid relationId);

    /*
     * HTAP exec alter table
     */
    RC OnAlterTable(Oid relid, Relation rel, AlterTableStmt *stmt);

    /*
     * HTAP exec drop table
     */
    RC OnDropTable(Oid relid, std::unordered_map<Oid, RelFileNode> **out_oid_del_info);

    /*
     * HTAP exec truncate table
     */
    RC OnTruncateTable(Oid relid, std::unordered_map<Oid, RelFileNode> **out_oid_del_info);

    /*
     * HTAP exec search delta table
     */
    RC OnSearchDelta(Oid relationId, uint64_t &rowCount, uint64_t &newRowCount, uint64_t &memSize);

public:
    /** Constructor. */
    HTAPInfra() : m_flush(nullptr), m_xLogRedoer(nullptr), m_shouldStopStatistics(false) {}

    /** Destructor. */
    ~HTAPInfra()
    {
        Terminate();
    }

    HTAP_DECLARE_CLASS_LOGGER();

    /** Helper for registering transaction callback for the current session (on-demand). */
    inline void EnsureTxnCallbacksRegistered()
    {
        // register transaction callbacks
        if (!u_sess->htap_cxt.callbacks_set) {
            RegisterXactCallback(HTAPXactCallback, NULL);
            RegisterSubXactCallback(HTAPSubxactCallback, NULL);
            u_sess->htap_cxt.callbacks_set = true;
        }
    }

    /** Explicit object initialization. */
    bool Initialize(const char *configFilePath);

    /** Explicit object termination. */
    void Terminate();

    /** Starts all services. */
    bool Start();

    /** Stops all services. */
    void Stop();

    /** Initializes all core (infrastructure) services. */
    bool InitializeCoreServices(const char *configFilePath);

    /** Initializes all HTAP applicative services. */
    bool InitializeApplicativeServices();

    /** Terminates all core services. */
    void TerminateCoreServices();

    /** Terminates all applicative services. */
    void TerminateApplicativeServices();

    /** Starts all (core and applicative) services. */
    bool StartAllServices();

    /** Stops all (core and applicative) services. */
    void StopAllServices();

    /** @var The single class instance. */
    static HTAPInfra *sInstance;

    /** @var The configuration manager. */
    HTAPCfg m_cfg;

    /** @var The Flush. */
    HTAPFlush *m_flush;

    /** @var The XLogRedoer. */
    HTAPXLogRedoer *m_xLogRedoer;

    /** @var Instance-level memory controller. */
    MemoryContext m_instanceMemoryContext;

    /** @var Designates HTAP should stop statistics manager. */
    bool m_shouldStopStatistics;

    /** Initializes configuration from file. */
    bool InitializeConfig(const char *configFilePath);

    /** Prints absolute configuration path. */
    void PrintCfgPath(const char *configFilePath);

    /** Things that must be in place before a hook executes. */
    bool checkBeforeModify();

    /** Destroys all statistics objects. */
    void TerminateStatistics();

    /** Starts statistics service thread. */
    bool StartStatistics();

    /** Stops statistics service thread. */
    void StopStatistics();

    /** Transaction event callback. */
    static void HTAPXactCallback(XactEvent event, void *arg);

    /** Sub-transaction event callback. */
    static void HTAPSubxactCallback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid,
        void *arg);

    /** Handle insert row. */
    RC HandleInsertRow(Oid relationId, ItemPointer ctid, TupleTableSlot *slot);

    /** Handle update row. */
    RC HandleUpdateRow(Oid relationId, ItemPointer ctid, TupleTableSlot *slot);

    /** Handle delete row. */
    RC HandleDeleteRow(Oid relationId, ItemPointer ctid, bool fromUpd);

    /** Handle create table. */
    RC HandleCreateTable(Oid parentId, Oid relationId);

    /** Handle drop table. */
    RC HandleDropTable(Oid relationId, std::unordered_map<Oid, RelFileNode> **out_oid_del_info);

    /** Handle drop table. */
    RC HandleTruncateTable(Oid relationId, std::unordered_map<Oid, RelFileNode> **out_oid_del_info);

    /** Handle alter table. */
    RC HandleAlterTable(Oid relationId, Relation rel, AlterTableStmt *stmt);

    /** Handle transaction event. */
    RC HandleXactEvent(XactEvent event);

    /** Handle sub-transaction event. */
    RC HandleSubXactEvent(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid);

    /** Handle quey of delyafor gs_imcs_mem_status command. */
    RC HandleSearchDelta(Oid relationId, uint64_t &rowCount, uint64_t &newRowCount, uint64_t &memSize);
};

/* * @brief Retrieves a reference to the xlog redoer. */
inline HTAPXLogRedoer *GetXLogRedoer()
{
    HTAPXLogRedoer *xLogRedoer = nullptr;
    HTAPInfra *htap = HTAPInfra::GetInstance();
    if (htap != nullptr) {
        xLogRedoer = htap->GetXLogRedoer();
    }
    return xLogRedoer;
}
} // namespace htap

#endif // HTAP_INFRA_H